package com.baosight.xcyber.tm.re.conf;

import com.baosight.xcyber.tm.re.observer.AdapterObserverI;
import com.baosight.xcyber.tm.re.observer.NodeObserverI;
import com.baosight.xcyber.tm.re.observer.ObjectObserverI;
import com.baosight.xcyber.tm.re.observer.RegistryObserverI;
import com.baosight.xcyber.tm.re.observer.ApplicationObserverI;
import com.zeroc.Ice.*;
import com.zeroc.IceGrid.*;
import com.zeroc.IceGrid.LocatorPrx;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.text.MessageFormat;

@Component
public class IceObserverConf {
    @Value("${ice.ip}")
    String ip;
    @Value("${ice.port}")
    String port;
    @Value("${ice.user}")
    String userName;
    @Value("ice.password")
    String password;

    @Autowired
    ApplicationObserverI applicationObserverServant;

    @Autowired
    AdapterObserverI adapterObserverI;

    @Autowired
    ObjectObserverI objectObserverI;

    @Autowired
    RegistryObserverI registryObserverI;

    @Autowired
    NodeObserverI nodeObserverI;

    @Bean
    public AdminSessionPrx init() throws PermissionDeniedException, ObserverAlreadyRegisteredException {
        //发现主节点名字
        System.out.println("发现主节点名字");
        String finderStr= MessageFormat.format(
                "Ice/LocatorFinder:tcp -h {0} -p {1} -t 6000",ip,port
        );
        Communicator communicator=Util.initialize();
        LocatorFinderPrx locatorFinderPrx = LocatorFinderPrx.uncheckedCast(
                communicator.stringToProxy(finderStr));
        String instanceName = locatorFinderPrx.getLocator().ice_getIdentity().category;
        //Locator And Registry
        System.out.println("Locator And Registry");
        LocatorPrx locatorPrx= LocatorPrx.checkedCast(
                locatorFinderPrx.ice_identity(new Identity("Locator",instanceName)));
        RegistryPrx localRegistry = locatorPrx.getLocalRegistry();
        //DefaultRouter and routerRegistry
        System.out.println("DefaultRouter and routerRegistry");
        communicator.setDefaultLocator(locatorPrx);
        com.zeroc.Ice.ObjectAdapter colloc = communicator.createObjectAdapter("");
        ObjectPrx router = colloc.addWithUUID(new ReuseConnectionRouter(locatorPrx));
        communicator.setDefaultRouter(RouterPrx.uncheckedCast(router));
        RegistryPrx registryPrx = localRegistry.ice_router(communicator.getDefaultRouter());
        //AdminSession
        System.out.println("AdminSession");
        registryPrx.ice_preferSecure(true);
        AdminSessionPrx adminSession = registryPrx.createAdminSession(userName, password);
        String replicaName = adminSession.getReplicaName();//Mater ==>>Logged into Master Registry else Logged into Slave Registry
        //admin And adminCallBackTemplate
        System.out.println("admin And adminCallBackTemplate");
        adminSession.ice_getConnection().setACM(null,null, java.util.Optional.of(ACMHeartbeat.HeartbeatAlways));
        AdminPrx admin = adminSession.getAdmin();
        ObjectPrx adminCallbackTemplate = adminSession.getAdminCallbackTemplate();
        String publisherEndpoints=null;
        for(com.zeroc.Ice.Endpoint endpoint : adminCallbackTemplate.ice_getEndpoints())
        {
            String endpointString = endpoint.toString();
            if(publisherEndpoints == null)
            {
                publisherEndpoints = endpointString;
            }
            else
            {
                publisherEndpoints += ":" + endpointString;
            }
        }
        communicator.getProperties().setProperty("CallbackAdapter.PublishedEndpoints",publisherEndpoints);
        String serverAdminCategory = admin.getServerAdminCategory();
        //registerObservers adapter
        System.out.println("registerObservers adapter");
        String category ="observer";
        ObjectAdapter adapter;
        String adapterName=adminCallbackTemplate.ice_getIdentity().category==null?"":"CallbackAdapter";
        adapter=communicator.createObjectAdapter(adapterName);
        adapter.activate();
        adminSession.ice_getConnection().setAdapter(adapter);
        //create servants and proxies
        Identity applicationObserverIdentity=new Identity(
                "application-" + java.util.UUID.randomUUID().toString(),
                category
        );
        Identity adapterObserverIdentity=new Identity(
                "adapter-" + java.util.UUID.randomUUID().toString(),
                category
        );
        Identity objectObserverIdentity=new Identity(
                "object-" + java.util.UUID.randomUUID().toString(),
                category
        );
        Identity registryObserverIdentity=new Identity(
                "registry-" + java.util.UUID.randomUUID().toString(),
                category
        );
        Identity nodeObserverIdentity=new Identity(
                "node-" + java.util.UUID.randomUUID().toString(),
                category
        );
        //ApplicationObserverI applicationObserverServant=new ApplicationObserverI();
        ApplicationObserverPrx applicationObserver=ApplicationObserverPrx.checkedCast(adapter.add(
                applicationObserverServant,applicationObserverIdentity
        ));
        AdapterObserverPrx adapterObserver=AdapterObserverPrx.checkedCast(adapter.add(
                adapterObserverI,adapterObserverIdentity
        ));
        ObjectObserverPrx objectObserver =ObjectObserverPrx.checkedCast(adapter.add(
                objectObserverI,objectObserverIdentity
        ));
        RegistryObserverPrx registryObserver=RegistryObserverPrx.checkedCast(adapter.add(
                registryObserverI,registryObserverIdentity
        ));
        NodeObserverPrx nodeObserver=NodeObserverPrx.checkedCast(adapter.add(
                nodeObserverI,nodeObserverIdentity
        ));
        adminSession.setObserversByIdentity(registryObserverIdentity,
                nodeObserverIdentity,
                applicationObserverIdentity,
                adapterObserverIdentity,
                objectObserverIdentity);
        System.out.println("end");
        return adminSession;
    }
    static private class ReuseConnectionRouter implements com.zeroc.Ice.Router
    {
        public
        ReuseConnectionRouter(com.zeroc.Ice.ObjectPrx proxy)
        {
            _clientProxy = proxy;
        }

        @Override
        public com.zeroc.Ice.Router.GetClientProxyResult
        getClientProxy(com.zeroc.Ice.Current current)
        {
            return new com.zeroc.Ice.Router.GetClientProxyResult(_clientProxy, false);
        }

        @Override
        public com.zeroc.Ice.ObjectPrx
        getServerProxy(com.zeroc.Ice.Current current)
        {
            return null;
        }

        @Override
        public com.zeroc.Ice.ObjectPrx[]
        addProxies(com.zeroc.Ice.ObjectPrx[] proxies, com.zeroc.Ice.Current current)
        {
            return new com.zeroc.Ice.ObjectPrx[0];
        }

        private final com.zeroc.Ice.ObjectPrx _clientProxy;
    }
}
